package com.xyy.saas.payment.util.mq;

import com.alibaba.fastjson.JSON;
import com.xyy.saas.payment.adpater.wechat.domain.EntrustDO;
import com.xyy.saas.payment.callback.core.result.CallbackRunner;
import com.xyy.saas.payment.common.RocketMqGroup;
import com.xyy.saas.payment.common.RocketMqTopic;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.enums.EntrustStatusEnum;
import com.xyy.saas.payment.cores.vo.CallbackResultVo;
import com.xyy.saas.payment.dao.model.EntrustPayInfo;
import com.xyy.saas.payment.service.EntrustPayInfoService;
import com.xyy.saas.payment.util.CallbackUtil;
import com.xyy.saas.payment.util.DateUtil;
import com.xyy.saas.payment.util.JSONUtils;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.ConsumeMode;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.apache.rocketmq.spring.core.RocketMQPushConsumerLifecycleListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;

@DependsOn("apolloUtil")
@Service
@RocketMQMessageListener(topic = RocketMqTopic.TOPIC_WX_ENTRUST_CALLBACK, consumerGroup = RocketMqGroup.GROUP_WX_ENTRUST_CALLBACK, consumeMode = ConsumeMode.ORDERLY)
public class WxEntrustCallback implements RocketMQListener<MessageExt>, RocketMQPushConsumerLifecycleListener , InitializingBean {

    private static final Logger LOGGER = LoggerFactory.getLogger(WxEntrustCallback.class);
    @Autowired
    private CallbackRunner callbackRunner;
    @Autowired
    private EntrustPayInfoService entrustPayInfoService;
    @Autowired
    private MqProducer mqProducer;
    @Autowired
    CallbackUtil callbackUtil;

    @Override
    public void onMessage(MessageExt messageExt) {
        String body = new String(messageExt.getBody());
        EntrustDO entrustDO = JSONUtils.parse2Object(body, EntrustDO.class);
        if (entrustDO==null){
            LOGGER.error("WxEntrustCallback MQ receive message fail domain is null");
            return;
        }
        // 委托类型 - 签约，解约
        String entrustType = "";
        try{
            // 签约信息查询
            EntrustPayInfo entrustPayInfo = entrustPayInfoService.selectByContractCode(entrustDO.getContractCode());
            if(null == entrustPayInfo) {
                LOGGER.error("WxEntrustCallback MQ query entrustPayInfo is not exist.");
                throw new Exception("签约信息为空");
            }
            entrustPayInfo.setOpenid(entrustDO.getOpenid());
            entrustPayInfo.setContractId(entrustDO.getContractId());
//            entrustPayInfo.setContractExpiredTime(entrustDO.getContractExpiredTime());
            // 委托状态变更
            if("ADD".equals(entrustDO.getChangeType())) {
                // 签约
                entrustPayInfo.setStatus(EntrustStatusEnum.ENTRUST_SUCCESS.getCode());
                entrustType = CallbackResultVo.TYPE_ENTRUST_SIGN_SUCCESS;
            }
            else if ("DELETE".equals(entrustDO.getChangeType())) {
                // 解约
                entrustPayInfo.setStatus(EntrustStatusEnum.ENTRUST_TERMINATE.getCode());
                entrustPayInfo.setContractTerminationMode(Integer.parseInt(entrustDO.getContractTerminationMode()));
                entrustType = CallbackResultVo.TYPE_ENTRUST_TERMINATE_SUCCESS;
            }
            else {
                throw new PaymentException("未知变更类型!");
            }
            entrustPayInfo.setUpdateTime(DateUtil.now());
            int count = entrustPayInfoService.updateByPrimaryKeySelective(entrustPayInfo);
            if (count<1){
                LOGGER.error("WxEntrustCallback MQ update entrustPayInfo fail entrustPayInfo:{}", JSON.toJSON(entrustPayInfo));
                throw new Exception("数据库异常!");
            }

            // 回调业务方
            Long unixTime = System.currentTimeMillis()/1000;
            callbackRunner.callback(entrustPayInfo.getContractCode(), entrustType, 0, 0, unixTime, entrustPayInfo.getCallback());

            LOGGER.info("WxEntrustCallback wxEntrust end entrustPayInfo:{}", JSON.toJSON(entrustPayInfo));
        }catch (Exception e){
            LOGGER.error("WxEntrustCallback MQ error domain:{}", JSON.toJSON(entrustDO));
            if (entrustDO.getCount()==16){
                LOGGER.error("WxEntrustCallback MQ error is 16 times domain:{}", JSON.toJSON(entrustDO));
                return ;
            }
            entrustDO.setCount(entrustDO.getCount()+1);
            mqProducer.syncSendDelayMsg(RocketMqTopic.TOPIC_WX_ENTRUST_CALLBACK, JSON.toJSONString(entrustDO), 1);
        }
    }

    @Override
    public void prepareStart(DefaultMQPushConsumer defaultMQPushConsumer) {
        defaultMQPushConsumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
        defaultMQPushConsumer.setConsumeTimestamp(UtilAll.timeMillisToHumanString3(System.currentTimeMillis()));
    }

    @Override
    public void afterPropertiesSet() throws Exception {

    }
}
